package validator

import (
	"fmt"
	"reflect"
)

type RangeTypes interface {
	int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64
}

type Border[T RangeTypes] struct {
	Value   T
	Include bool
}

type Range[T RangeTypes] struct {
	getValue func(reflect.Value) T
	min      *Border[T]
	max      *Border[T]
}

func NewRangeValidator[T RangeTypes](
	min *Border[T],
	max *Border[T],
	getValue func(reflect.Value) T) *Range[T] {
	return &Range[T]{
		getValue: getValue,
		min:      min,
		max:      max,
	}
}
func (r *Range[T]) String() string {
	var str string
	if r.min != nil {
		if r.min.Include {
			str = fmt.Sprintf("[%v", r.min.Value)
		} else {
			str = fmt.Sprintf("(%v", r.min.Value)
		}
	} else {
		str = "("
	}
	if r.max != nil {
		if r.max.Include {
			str = fmt.Sprintf("%s:%v]", str, r.max.Value)
		} else {
			str = fmt.Sprintf("%s:%v)", str, r.max.Value)
		}
	} else {
		str = fmt.Sprintf("%s:)", str)
	}
	return str
}

func (r *Range[T]) IsValidate(field string, data reflect.Value) error {
	var v = r.getValue(data)
	if r.min != nil {
		if r.min.Include {
			if v < r.min.Value {
				return fmt.Errorf("field [%s]'s must great then or equals %v", field, r.min.Value)
			}
		} else {
			if v <= r.min.Value {
				return fmt.Errorf("field [%s]'s must great then %v", field, r.min.Value)
			}
		}
	}
	if r.max != nil {
		if r.max.Include {
			if v > r.max.Value {
				return fmt.Errorf("field [%s]'s must less then or equals %v", field, r.max.Value)
			}
		} else {
			if v >= r.max.Value {
				return fmt.Errorf("field [%s]'s must less then %v", field, r.max.Value)
			}
		}
	}
	return nil
}
